package com.foreverwin.jzymes.production.cnc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.domain.AgvReqLog;
import com.foreverwin.jzymes.common.domain.CncReqLog;
import com.foreverwin.jzymes.common.domain.TranshipInfra;
import com.foreverwin.jzymes.common.mapper.AgvReqLogMapper;
import com.foreverwin.jzymes.common.mapper.CncReqLogMapper;
import com.foreverwin.jzymes.common.mapper.SfcBatchPassLogAdviceMapper;
import com.foreverwin.jzymes.common.mapper.TranshipInfraAdviceMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.event.AppEventPublisher;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import com.foreverwin.jzymes.production.cnc.service.ICncSfcPassAdviceService;
import com.foreverwin.jzymes.production.tool.service.IToolUsageAdviceService;
import org.apache.activemq.command.ActiveMQTopic;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class CncSfcPassAdviceServiceImpl implements ICncSfcPassAdviceService {

    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    IToolUsageAdviceService toolUsageAdviceService;
    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    ICarrierBindAdviceService carrierBindAdviceService;
    @Autowired
    ITranshipInfraService transhipInfraService;
    @Autowired
    IProductionShiftService productionShiftService;
    @Autowired
    CncReqLogMapper cncReqLogMapper;
    @Autowired
    SfcBatchPassLogAdviceMapper sfcBatchPassLogAdviceMapper;
    @Autowired
    AgvReqLogMapper agvReqLogMapper;
    @Autowired
    TranshipInfraAdviceMapper transhipInfraAdviceMapper;
    @Autowired
    JmsMessagingTemplate jmsTemplate;
    @Autowired
    AppEventPublisher appEventPublisher;


    /**
     * 一夹自动线本体过站
     *
     * @param cncReqLog
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void sfcPassByCarrier( CncReqLog cncReqLog ){

        /**检查字段*/
        checkFieldsForCarrierPass( cncReqLog );
        cncReqLog.setCreatedDateTime( new Date() );

        /**检查设备*/
        //Map<String,Object> resourceMap = resourceAdviceService.existResource( cncReqLog.getSite(), cncReqLog.getResrce() );
        /**检查工序*/
        //String operation = resourceAdviceService.findOperationByResource( resourceMap );

        //List<CarrierBind> carrierBindList = carrierBindAdviceService.existCarrierBindonBind( cncReqLog.getSite(), cncReqLog.getCarrier() );

        /**检查待过站工序是否是本体当前所在工序*/
        //Assert.isTrue( operation.equals( carrierBindList.get(0).getNextOperation() ) , I18nUtil.getI18nText( "common.carrierNotPassOnOperation", new String[]{ cncReqLog.getCarrier(), carrierBindList.get(0).getNextOperation(), operation } ) );

        /**本体过站*/
        //commonService.sfcPassByCarrier( cncReqLog.getSite(),cncReqLog.getCarrier(), cncReqLog.getResrce(), cncReqLog.getCreatedDateTime() );

        /**统计刀具寿命*/
        //toolUsageAdviceService.addToolUsage( cncReqLog.getSite(), cncReqLog.getMachineType(), cncReqLog.getResrce() );

        /**保存上报信息*/
        cncReqLog.setHandle( BOHandleUtil.buildCncReqLogHandle() );
        cncReqLogMapper.insertCncReqLog( cncReqLog );
    }

    /**
     * 检查cnc接驳站上传字段
     *
     * @param cncReqLog
     */
    public void checkFieldsForCarrierPass( CncReqLog cncReqLog ){
        /**检查站点*/
        siteAdviceService.existSite( cncReqLog.getSite() );
        /**查询机种*/
        String itemGroup = itemGroupAdviceService.findItemGroupBySite( cncReqLog.getSite() );
        cncReqLog.setMachineType( itemGroup );
        /**检查本体*/
        Assert.hasText( cncReqLog.getCarrier(), I18nUtil.getI18nText( "common.carrierNotBlank" ));
        /**检查上传日期*/
        Assert.notNull( cncReqLog.getSendTime(), I18nUtil.getI18nText( "production.cnc.sendTimeNotNull" ) );
    }

    /**
     * 一夹手工线过站
     *
     * @param agvReqLog
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void sfcPassByTrayQty( AgvReqLog agvReqLog ){

        /**检查上报字段*/
        checkFieldsForTrayQtyPass( agvReqLog );
        agvReqLog.setCreatedDateTime( new Date() );

        /**检查接驳站*/
        //resourceAdviceService.existResource( agvReqLog.getSite(), agvReqLog.getTranship() );

        /**查询Tray盘本体数系统规则*/
        String ruleValue = systemRuleAdviceService.existSystemRule( agvReqLog.getSite(), Constants.SYSTEM_RULE_CARRIER_QTY_PER_TRAY );
        Long  trayCapacity = NumberUtils.createLong( ruleValue );

        /**计算本体数*/
        Long carrierQty = agvReqLog.getTrayQty() * trayCapacity;

        /**AGV上传一夹熟料过站*/
        if( agvReqLog.getItemType().equals( "M" ) && resourceAdviceService.isCNC1( agvReqLog.getSite(), agvReqLog.getTranship() ) ){
            /**工令数量过站*/
            commonService.sfcPassByQty( agvReqLog.getSite(), agvReqLog.getTranship(), carrierQty, agvReqLog.getCreatedDateTime() );

            /**发布2H事件*/
            JSONObject eventData = new JSONObject();
            eventData.put( "SITE", agvReqLog.getSite() );
            eventData.put( "RESRCE", agvReqLog.getTranship() );
            eventData.put( "CARRIER_QTY", carrierQty );
            AppEvent<JSONObject> appEvent = new AppEvent<>( this );
            appEvent.setName( "TRAY_CHECK_OUT_EVENT" );
            appEvent.setData( eventData );
            appEventPublisher.publishEvent( appEvent );
        }

        /**保存接驳站数据*/
        saveTransshipInfra( agvReqLog, trayCapacity );

        /**保存AGV上报信息记录*/
        agvReqLog.setHandle( BOHandleUtil.buildAgvReqLogHandle() );
        agvReqLogMapper.insertAgvReqLog( agvReqLog );
    }

    /**
     * 处理cnc设备上传不良本体数量
     *
     * @param site
     * @param resrce
     * @param ngQty
     * @param sendTime
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void receiveNgCarrierFromQueue( String site, String resrce, Long ngQty, Date sendTime ){
        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查CNC接驳站编号*/
        resourceAdviceService.existResource( site, resrce );
        /**检查NG数量*/
        Assert.isTrue( ngQty != null && ngQty > 0, I18nUtil.getI18nText( "production.cnc.carrierNgQtyNotValid", new Object[]{ ngQty } ) );
        /**检查上传日期*/
        Assert.notNull( sendTime, I18nUtil.getI18nText( "production.cnc.sendTimeNotNull" ) );

        /**查询机种*/
        String itemGroup = itemGroupAdviceService.findItemGroupBySite( site );

        /**调整一夹待过站数据*/
        List<Map<String,Object>> itemMembers = itemGroupAdviceService.findItemGroupMember( site, itemGroup );
        for( Map<String,Object> itemMember : itemMembers ){
            commonService.reduceOpenSfcBatchPassLogQty( site, (String) itemMember.get( "ITEM_BO" ), resrce, ngQty );
        }

        /**调整接驳站本体数量*/
        String tranship = resourceAdviceService.findTranship( site, resrce );
        String shift = productionShiftService.findShift( site, new Date() );
        Date[] dateRange = productionShiftService.findShiftRange( site, shift );
        TranshipInfra transhipInfra = transhipInfraAdviceMapper.selectTranshipInfraByDate( site, tranship, shift, dateRange[0], dateRange[1] );
        if( transhipInfra == null ){
            transhipInfra = new TranshipInfra();
            transhipInfra.setHandle( BOHandleUtil.buildTranshipInfraHandle() );
            transhipInfra.setSite( site );
            transhipInfra.setShift( shift );
            transhipInfra.setResrce( tranship );
            transhipInfra.setCreatedDateTime( new Date() );
            transhipInfra.setProductQty( -1 * ngQty );
            transhipInfraService.insertTranshipInfra( transhipInfra );
        }else{
            transhipInfra.setProductQty( transhipInfra.getProductQty() - ngQty );
            transhipInfraService.updateTranshipInfra( transhipInfra );
        }

    }

    /**
     * 保存接驳站数据
     *
     * @param agvReqLog
     * @param trayCapacity
     */
    public void saveTransshipInfra( AgvReqLog agvReqLog, Long trayCapacity ){
        String shift = productionShiftService.findShift( agvReqLog.getSite(), agvReqLog.getCreatedDateTime() );
        Date[] dateRange = productionShiftService.findShiftRange( agvReqLog.getSite(), shift );
        TranshipInfra transhipInfra = transhipInfraAdviceMapper.selectTranshipInfraByDate( agvReqLog.getSite(), agvReqLog.getTranship(), shift, dateRange[0], dateRange[1] );
        Long carrierQty = agvReqLog.getTrayQty() * trayCapacity;
        if( transhipInfra == null ){
            transhipInfra = new TranshipInfra();
            transhipInfra.setHandle( BOHandleUtil.buildTranshipInfraHandle() );
            transhipInfra.setSite( agvReqLog.getSite() );
            transhipInfra.setShift( shift );
            transhipInfra.setResrce( agvReqLog.getTranship() );
            transhipInfra.setCreatedDateTime( agvReqLog.getCreatedDateTime() );
            if( agvReqLog.getItemType().equals( "M" ) ){
                transhipInfra.setProductQty( carrierQty );
            }else{
                transhipInfra.setRawQty( carrierQty );
            }
            transhipInfraService.insertTranshipInfra( transhipInfra );
        }else{
            if( agvReqLog.getItemType().equals( "M" ) ){
                transhipInfra.setProductQty( transhipInfra.getProductQty() + carrierQty );
            }else{
                transhipInfra.setRawQty( transhipInfra.getRawQty() + carrierQty );
            }
            transhipInfraService.updateTranshipInfra( transhipInfra );
        }

        /**发送数据到页面*/
        JSONObject eventData = new JSONObject();
        eventData.put( "SITE", transhipInfra.getSite() );
        eventData.put( "RESRCE", transhipInfra.getResrce() );
        eventData.put( "RAW_NUM", transhipInfra.getRawQty() );
        eventData.put( "CLINKER_NUM", transhipInfra.getProductQty() );
        AppEvent<JSONObject> appEvent = new AppEvent<>( this );
        appEvent.setName( "TRANSHIP_TRANSFER_EVENT" );
        appEvent.setData( eventData );
        ActiveMQTopic topic = new ActiveMQTopic( "MES_APP_EVENT_INFRA" );
        jmsTemplate.convertAndSend( topic, appEvent );

    }



    /**
     * 检查AGV上报字段
     *
     * @param agvReqLog
     */
    public void checkFieldsForTrayQtyPass( AgvReqLog agvReqLog ){
        /**检查站点*/
        siteAdviceService.existSite( agvReqLog.getSite() );
        /**查询机种*/
        String itemGroup = itemGroupAdviceService.findItemGroupBySite( agvReqLog.getSite() );
        agvReqLog.setMachineType( itemGroup );
        /**检查熟料盘数*/
        Assert.isTrue( agvReqLog.getTrayQty() != null && agvReqLog.getTrayQty() > 0, I18nUtil.getI18nText( "production.cnc.trayQtyNotValid", new Object[]{ agvReqLog.getTrayQty() } ) );
        /**检查物料类型*/
        Assert.hasText( agvReqLog.getItemType(), I18nUtil.getI18nText( "production.cnc.itemTypeNotBlank" ) );
        /**检查上传日期*/
        Assert.notNull( agvReqLog.getSendTime(), I18nUtil.getI18nText( "production.cnc.sendTimeNotNull" ) );
    }
}
